package com.xmim.server.examples;

import com.xmim.fulcrum.FulcrumCounter;
import com.xmim.fulcrum.FulcrumFactory;
import com.xmim.fulcrum.node.FulcrumServiceNode;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.atomic.AtomicValue;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.RetryNTimes;

public class ZKFulcrumCounter implements FulcrumCounter {
    private final DistributedAtomicLong onlineCount;
    private final FulcrumFactory fulcrumFactory;
    private final CuratorFramework client;
    private final ZKFulcrumDiscover discover;

    private long value;


    public ZKFulcrumCounter(ZKFulcrumDiscover discover, String path) {
        this.discover = discover;
        this.client = discover.getClient();
        this.fulcrumFactory = discover.getFactory();
        this.onlineCount = new DistributedAtomicLong(client, path, new RetryNTimes(10, 30));
    }

    @Override
    public boolean increment() {
        while (true) {
            try {
                AtomicValue<Long> val = onlineCount.increment();
                value = val.postValue();

                FulcrumServiceNode localNode = this.discover.getLocalNode();
                localNode.incrementBalance();
                byte[] payload = this.fulcrumFactory.getCodec().encode(localNode);
                client.setData().forPath(localNode.getPath(), payload);

                return val.succeeded();
            } catch (Exception e) {
                return false;
            }
        }

    }

    @Override
    public boolean decrement() {
        try {
            AtomicValue<Long> val = onlineCount.decrement();
            value = val.postValue();

            FulcrumServiceNode localNode = this.discover.getLocalNode();
            localNode.decrementBalance();
            byte[] payload = this.fulcrumFactory.getCodec().encode(localNode);
            client.setData().forPath(localNode.getPath(), payload);

            return val.succeeded();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    @Override
    public long getValue() {
        try {
            return onlineCount.get().postValue();
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }
}
